/*
 * File: Hangman.java
 * ------------------
 * Implementation for the Assignment 4: Hangman Game
 */

import acm.program.*;
import acm.util.*;

public class Hangman extends ConsoleProgram {

	/**
	 * this value is not prepared to be changed
	 * but its good to set it up as a constant
	 * 
	 */
	private static final int INITIAL_GUESSES = 8;
	
	/**
	 * number of guesses left in the round
	 */
	private int guessesLeft = INITIAL_GUESSES;
	
	/**
	 * place to display hangman graphically
	 */
	private HangmanCanvas canvas;
	
	/**
	 * Hangman initialization
	 */
	public void init(){
		canvas = new HangmanCanvas();
		add(canvas);
	}
	
	/**
	 * Gets a random word from HangmanLexicon
	 * @return a String that represents a word
	 */
	private String getRandomWord(){
		HangmanLexicon hangmanLexicon = new HangmanLexicon();
		RandomGenerator rgen = RandomGenerator.getInstance();
		
		String word = hangmanLexicon.getWord(rgen.nextInt( hangmanLexicon.getWordCount() - 1 ));
		return word;
	}
	
	/**
	 * Determins when the game is won
	 * @param word
	 * @param hiddenWord
	 * @return
	 */
	private boolean gameWon(String word, String hiddenWord){
		return word.equals(hiddenWord);
	}
	
	
    public void run() {    	
    	while (true){
    		String word = getRandomWord();
	    	String hiddenWord = getHiddenWord(word);
	    	
	    	resetGame(hiddenWord);
	    	
	    	while(guessesLeft>0 && !gameWon(word, hiddenWord)){
	    		println("Your word now looks like this: " +  hiddenWord );
		    	println("You have " + guessesLeft + " guesses left");
		    	println("Your guess: ");
		    	String guess = readLine();
		    			    
		    	hiddenWord = makeAGuess(guess, word, hiddenWord);
	    	}
	    	
	    	if (guessesLeft==0){
	    		showGameLost(word);
	    	}
	    	else{
	    		showGameWon(word);
	    	}
    	}
	}
    
    /**
     * Displays a message when the user wins
     * @param word
     */
    private void showGameWon(String word){
		println("You guessed the word" + word );
		println("You lose");
		readLine();
    }
    
    /**
     * Displays a message when the user losses
     * @param word
     */
    private void showGameLost(String word){
    	println("You're completely hung.");
		println("The word was " + word );
		println("You lose");
		readLine();
    }
    
    /**
     * Resets the game to initial state
     * @param hiddenWord
     */
    private void resetGame(String hiddenWord){
    	guessesLeft=INITIAL_GUESSES;
    	getConsole().clear();
    	println("Welcome to Hangman!");
    	canvas.reset();
    	canvas.displayWord(hiddenWord);
    }
    
    /**
     * Guesses a letter from the word an display message according results
     * @param guess
     * @param word
     * @param hidden
     * @return
     */
    private String makeAGuess(String guess, String word, String hidden){
    	if (guess.length()!=1){
    		println("Please enter one letter as a guess");
    		return hidden;
    	}
    	Character letterGuessed = Character.toUpperCase(guess.charAt(0));
    	
    	if (hidden.indexOf(letterGuessed)!=-1){
    		println("You have already guessed that letter. Please enter another one:");
    		return hidden;
    	}
    
    	// letter doesnt exist
    	if (word.indexOf(letterGuessed)==-1){
    		println("Oh! that letter does not exist");
    		guessesLeft--;
    		canvas.noteIncorrectGuess(letterGuessed);
    		return hidden;
    	}
    	// letter exists, find it
    	else{
    		letterGuessed = Character.toUpperCase(letterGuessed); 
    		for (int i=0; i<word.length(); i++){
    			char charFromWord = Character.toUpperCase(word.charAt(i));
    			if (charFromWord==letterGuessed){
    				hidden = hidden.substring(0, i) + letterGuessed + hidden.substring(i+1);
    				canvas.displayWord(hidden);
    			}
    		}
    	}
    	
    	return hidden;
    }
    
    /**
     * Hides a word
     * @param word
     * @return
     */
    private String getHiddenWord(String word){
    	String hidden = "";
    	for (int c = 0; c<word.length(); c++){
    		hidden += '-';
    	}
    	
    	return hidden;
    }

}
